// Mayank Verma
// 2010048
// 
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>

int m=0;   // m represents number of lines in the text file, i.e. number of usernames... WOULD BE CALCULATED LATER
void hash(int c);
unsigned int find_key(int unq,int i,int c);
struct node
{
 char username[50];
 char password[50];
} *table;



///////////////////////////////////////////
//                                                        MAIN
///////////////////////////////////////////

void main()
{       printf("\n\n");
        int c,unq,i=0;
        unsigned int key;
        char user_m[50];
        m=count_usernames();    
        //save_names();
        table=malloc(m*sizeof(struct node));
        printf("\n1. Linear Probing\n2. Quadratic Probing \n3. Double Hashing\n\nEnter your Choice: ");
        scanf("%d", &c);
        hash(c);
        printf("\nEnter Username:");
        scanf("%s",user_m);
        unq=convert_ascii_uniq(user_m);
        key=find_key(unq,i,c);
        check(user_m,key,unq,c,i);

} //////////////////////////////////////////             MAIN ENDS



/*void save_names()                 // SAVES ALL USERNAMES IN A FILE "only_names.txt"
{
        FILE *fs;
        FILE *ft;
        int i=0, j=0;
        char ch;
        ft=fopen("only_names.txt", "w");        
        fs=fopen("data.txt","r");
        while ( 1 )
         {
                ch = fgetc ( fs ) ;
                if ( ch == EOF )
                 break ;
                if (ch==' ')
                 do {
                     ch = fgetc(fs);
                    } while (ch!='\n');
                 fputc ( ch, ft ) ;
         }
        fclose ( fs ) ;
        fclose ( ft ) ;
        ft=fopen("names.txt", "r");
        printf("\nUsernames in ''only_names'' file are: \n");
        while (1)
         {
             ch=fgetc(ft);
             if (ch == EOF)
                   break;             
             printf("%c",ch);
         }

}*/


int convert_ascii_uniq(char s[])
{

 int i=0;
 unsigned int key=0;
 for (i=0; i<strlen(s); i++)
  {
   if (i==0)
    { key+=1.5*(int)(s[i]);}
   else
    {key+=(int)(s[i]);}
  }
  
 return key;
}

void hash(int c)
{
        FILE *fp;
        char usr[50];
        char pass[50];
        unsigned int key, unq_ascii;
        int i = 0;
        fp=fopen("data.txt","r");
        while(fscanf(fp,"%s %s",usr,pass)!=EOF)
        {
            unq_ascii = convert_ascii_uniq(usr);      
            key = find_key(unq_ascii,i,c);
            table_fill(unq_ascii,usr,pass,c,i,key);
        }
        fclose(fp);
}


int table_fill(int unq,char usr[],char pass[],int c,int i,unsigned int key)
{    
     if(strlen(table[key].username)!=0)
        {
                i+=1;
                key = find_key(unq,i,c);
                table_fill(unq,usr,pass,c,i,key);
        }
     else
        {
                strcpy(table[key].username,usr);
                strcpy(table[key].password,pass);
        }
}


unsigned int find_key(int unq,int i,int c)
{
    unsigned int key;
    switch(c)
    {
    case 1:key=(unq+i)%m;                           // Linear Probing
           break;
    case 2:key=(unq+(i^2))%m;                       // Quadratic Probing
           break;
    case 3:key=((unq+i)+(unq+(i^2)))%m;                            // Double Hashing
           break;
    default: printf("\nError:Invalid Choice\n");
           break;
    }
    return key;
}

int count_usernames()
{
                
        FILE *fp;
        char ch ;
        fp=fopen("data.txt","r");
        while (1)
         {
             ch=fgetc(fp);
             if (ch == EOF)
                   break;
             if (ch=='\n')
              m++;
         }
        fclose(fp);
        printf("\nNumber of Usernames is: %d", m);
        printf("\n");
        return m;
}

int check(char user_m[50],unsigned int key,int unq,int c,int i)
{       
        int tries=0;
        char usr[50];
        char pass2[50];
        char pass[15];  
        strcpy(usr,table[key].username);
        if(strcmp(usr,user_m)==0)
        {       strcpy(pass,table[key].password);
                do
                {
                        printf("\nEnter the password: ");
                        scanf("%s",pass2);
                        if(strcmp(pass2,pass)==0)
                        {
                                printf("\nPassword correct!\n\n");
                                return 0;
                        }
                        else
                        {
                                printf("\nPassword incorrect!! Try again!\n");
                                printf("\nYou have %d try/tries left\n", 2-tries);
                                tries++;
                        }
                 }while(tries!=3);
                printf("\nToo many tries! Access Denied!\n\n"); 
        }
        else
        {
                i+=1;
                key=find_key(unq,i,c);
                if((strlen(table[key].username)==0) || (i>m) )
                {
                        printf("Error: No such Username!!\n");
                        return 0;
                }
                else
                        check(user_m,key,unq,c,i);
        }
}

